<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!--本地下载:  先下载  在引入  再使用 -->
    <script src="../js/vue.js"></script>

    <!-- CDN -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script> -->
</head>
<body>
    <!-- 在没有使用vue之前 -> 它就是一个普通的文本 -->
    <div id="app">
        <p>
            message:{{message}} 
        </p>
        <p>
            count: {{count}}
        </p>
        <p>
            say:{{say()}}
        </p>
    </div>
</body>
<script>
    // ajax({type,url,data,async,success})  传入一个对象作为参数(同时传入多个数据,不同的键名执行不同的代码逻辑)
</script>
<script>

    // 声明式渲染
    function MyVue(options){
        // this-> 构造函数在执行过程中创建的实例化对象  {}

        // el挂载的元素  "#app" 字符串
        // data挂载的数据  
        // methods 挂载的方法  
        let {el,data,methods} = options;


        // 通过渲染器获取挂载的元素
        this.$el = document.querySelector(el);
        let template = this.$el.outerHTML;  //获取元素本身及其内部的html结构
        console.log(template);

        var _this = this;

        render()

        function render(){

            /*  template => 初始的模板 -> 重复利用(考虑到数据更新)
                    <p>
                        message:{{message}} 
                    </p>
                    <p>
                        count: {{count}}
                    </p>
                    <p>
                        say:{{say()}}
                    </p>
            
            
            */

            // 从下标为0的位置开始向后匹配(g)  -> 有就返回匹配的内容(数组),下次从匹配位置的后一位继续向后匹配,匹配不到返回null
            // var reg = /{{.+}}/g;
            // var result = reg.exec(template);  // ['{{message}}']
            // console.log(result);
            // var result = reg.exec(template);  // ['{{count}}']
            // console.log(result);
            // var result = reg.exec(template);  // ['{{say}}']
            // console.log(result);
            // var result = reg.exec(template);  // null
            // console.log(result);
            let reg = /{{.+}}/g;
            let result = null;
            

            // 每次循环时 先将匹配的结果赋值给result => 成功返回[] (继续循环)   失败=> null(跳出循环)
            // 再将解析的结果作为while循环的表达式  -> 条件
            
            var html = template; // 将原本的template复制一份  -> 不修改原本的
            while(result = reg.exec(html)){
                console.log(result);  // ['{{message}}']  

                let isFunction = false;
                let key = result[0].slice(2,-2);
                // console.log(key);   //没有处理  

                if(key.endsWith("()")){  //key => say()  以()结尾
                    isFunction = true;
                    key = key.slice(0,-2)
                }
                console.log(key);  //键名(字符串)  "message" "count" "say"


                var val = null;
                if(key in data){ //数据在data中挂载了
                    val = data[key];
                }else if(key in methods && isFunction==true){//数据在methods中挂载了,且是一个函数
                    val = methods[key].call(_this)
                }else{  //不考虑计算属性  -> 既不是data中的数据,也不是methods中的方法
                    var err = new Error(`Property or method "${key}" is not defined on the instance but referenced during render`);
                    throw err;
                }   
                console.log(result[0],val);
                // console.log(result);  // ['{{message}}'] 
                html = html.replace(result[0],val);  // 返回替换后的新字符串
            }
            
            
            _this.$el.outerHTML = html;
          



        }




    }
    
    
    var vm = new MyVue({   // 注意Vue中的绝大部分功能都是依赖于options(选项)参数实现的
        el:"#app",  //挂载的元素(css选择器)  => #app
        data:{      //挂载的数据  => 可以有多条(对象) -> 可以在挂载的元素内使用(对应数据名称使用)
            count:1,
            message:"hello world",
            msg:"你好"
        },
        methods:{   // 挂载的方法 => 执行既定的内容  -> 可以在挂载的元素内使用(对应函数名称使用)
            say:function(){
                // console.log("this",this);  // 在Vue实例中methods,computed,watch中 方法的this都指向当前Vue实例
                return "你好"
                // return this.msg;
            }, 
        }
    })






</script>
</html>